package main

import (
	"fmt"
	"math"
	"math/big"
	"runtime"
	"time"
)

// 使用以下序列在协程中计算 pi：开启一个协程来计算公式中的每一项并将结果放入通道，main() 函数收集并累加结果，打印出 pi 的近似值

func main() {
	// ts := time.Now()
	n := 10000000
	// Pi := calculatePi(n)
	// fmt.Println("Pi: ", Pi)
	runtime.GOMAXPROCS(2)

	ti1 := time.Now()
	// fmt.Println("Cost time: ", ti1.Sub(ts))

	Pi2 := calcPi(n)
	ti2 := time.Now()
	fmt.Println("Pi2: ", Pi2)
	fmt.Println("Cost time: ", ti2.Sub(ti1))
}

func calculatePi(n int) float64 {
	chanRat := make(chan *big.Rat)
	res := make(chan float64)
	go func() {
		for i := 0; i < n; i++ {
			sig := math.Pow(-1, float64(i))
			chanRat <- big.NewRat(4*int64(sig), int64(2*i+1))
		}
		close(chanRat)
	}()

	go func() {
		r := <-chanRat
		for i := 1; i < n; i++ {
			r.Add(r, <-chanRat)
		}
		f, _ := r.Float64()
		res <- f
	}()
	return <-res
}

func calcPi(n int) float64 {
	ch := make(chan float64)
	go func() {
		for i := 0; i < n; i++ {
			term(ch, float64(i))
		}

	}()

	var res float64
	for i := 0; i < n; i++ {
		res += <-ch
	}
	return res
}

func term(ch chan float64, k float64) {
	ch <- 4.0 * math.Pow(-1, k) / float64(2*k+1)
}
